<?php

namespace app\task\cron;

use yunwuxin\cron\Task;
use think\facade\Db;

/**
 * 代理商，供应商余额不足预警
 */
class BalanceWarning extends Task
{
    // 短信类型
    const SMS_TYPE_SUPPLIER_BALANCE_WARNING = 1; // 供应商余额预警
    const SMS_TYPE_AGENT_BALANCE_WARNING = 2; // 代理商余额预警

    /**
     * 需要处理的模块
     * @var array
     */
    protected $module = ['supplier', 'agent'];

    /**
     * 每分钟执行
     */
    protected function configure()
    {
        // 分 时 日 月 周
        $this->expression = '* * * * *';
    }

    protected function handle()
    {
        echo '开始余额预警' . PHP_EOL;
        $lockKey = 'agent_supplier_balance_warning';
        $lockVal = cache($lockKey);
        if ($lockVal) {
            echo '还在处理呢' . PHP_EOL;

            return true;
        }

        cache($lockKey, 1, 500);

        foreach ($this->module as $m) {
            if (method_exists($this, $method = "_{$m}")) {
                $this->$method();
            }
        }

        cache($lockKey, null);

        echo '结束余额预警' . PHP_EOL;
    }

    /**
     * 供应商余额预警，把需要预警的写入 sms_log
     */
    protected function _supplier()
    {
        $list = Db::name('supplier_balance_warning_config')
            ->field('id, supplier_id, serv_type, balance, mobile')
            ->where('status', 1)
            ->where('last_warning_time', '<', time() - 1800) // 30分钟内不重复推送
            ->select()
            ->toArray();
        if (empty($list)) {
            echo '没有需要余额预警的供应商' . PHP_EOL;
            return true;
        }

        $supplier = \app\admin\model\SupplierBalanceWarningConfig::getSupplierList();
        $supplier = array_column($supplier, null, 'uniqueId');
        $smsLog = [];
        $configIds = [];
        $today = date('Y-m-d');
        foreach ($list as $v) {
            $uniqueId = $v['supplier_id'] . '-' . $v['serv_type'];
            if (!isset($supplier[$uniqueId]) || yuan2fen($v['balance']) < $supplier[$uniqueId]['balance']) {
                continue;
            }

            $configIds[] = $v['id'];

            // 每天，一个供应商最多通知 3 次
            $times = Db::name('sms_log')
                ->whereTime('created_at', 'between', [$today, $today . ' 23:59:59'])
                ->where('record_id', $v['supplier_id'])
                ->where('type', self::SMS_TYPE_SUPPLIER_BALANCE_WARNING)
                ->count();
            if ($times >= 3) {
                continue;
            }

            $smsLog[] = [
                'type' => self::SMS_TYPE_SUPPLIER_BALANCE_WARNING,
                'params' => json_encode([
                    'template' => 'SMS_259480331', // 您在供应商${name}的账户余额不足，请及时充值。
                    'data' => [
                        'name' => $supplier[$uniqueId]['name'],
                    ],
                ], JSON_UNESCAPED_UNICODE),
                'mobile' => $v['mobile'],
                'result' => '',
                'record_id' => $v['supplier_id'],
            ];
        }
        if (empty($smsLog)) {
            echo '[供应商]没有需要处理的数据' . PHP_EOL;
            return true;
        }

        Db::startTrans();
        try {
            Db::name('sms_log')
                ->insertAll($smsLog);
            Db::name('supplier_balance_warning_config')
                ->whereIn('id', $configIds)
                ->update([
                    'last_warning_time' => time(),
                ]);

            Db::commit();
        } catch (\Exception $e) {
            Db::commit();

            echo '[供应商]数据插入失败：' . $e->getMessage() . PHP_EOL;
        }
        return true;
    }

    /**
     * 代理商余额预警，把需要预警的写入 sms_log
     */
    protected function _agent()
    {
        $list = Db::name('agent_balance_warning_config')
            ->field('id, agent_id, balance, mobile, last_warning_time')
            ->where('status', 1)
            ->where('last_warning_time', '<', time() - 1800) // 30分钟内不重复推送
            ->select()
            ->toArray();
        if (empty($list)) {
            echo '没有需要余额预警的代理商' . PHP_EOL;
            return true;
        }

        $agentIds = array_column($list, 'agent_id');
        $agent = Db::name('agent')
            ->whereIn('id', $agentIds)
            ->where('balance_last_updated_at', '>=', date('Y-m-d H:i:s', time() - 90 * 60)) // 90 分钟内，余额没变化，不通知
            ->column('balance, balance_last_updated_at', 'id');

        $smsLog = [];
        $configIds = [];
        $today = date('Y-m-d');
        foreach ($list as $v) {
            if (!isset($agent[$v['agent_id']]) || yuan2fen($v['balance']) < $agent[$v['agent_id']]['balance']) {
                continue;
            }

            $configIds[] = $v['id'];

            // 每天，一个代理商最多通知 3 次
            $times = Db::name('sms_log')
                ->whereTime('created_at', 'between', [$today, $today . ' 23:59:59'])
                ->where('record_id', $v['agent_id'])
                ->where('type', self::SMS_TYPE_AGENT_BALANCE_WARNING)
                ->count();
            if ($times >= 3) {
                continue;
            }

            $smsLog[] = [
                'type' => self::SMS_TYPE_AGENT_BALANCE_WARNING,
                'params' => json_encode([
                    'template' => 'SMS_259825273', // 尊敬的商家,您的帐户余额不足，为了您能正常向用户提供服务，请查看帐户详情。
                ]),
                'mobile' => json_encode([$v['mobile']]),
                'result' => '',
                'record_id' => $v['agent_id'],
            ];
        }
        if (empty($smsLog)) {
            echo '[代理商]没有需要处理的数据' . PHP_EOL;
            return true;
        }

        Db::startTrans();
        try {
            Db::name('sms_log')
                ->insertAll($smsLog);
            Db::name('agent_balance_warning_config')
                ->whereIn('id', $configIds)
                ->update([
                    'last_warning_time' => time(),
                ]);

            Db::commit();
        } catch (\Exception $e) {
            Db::commit();

            echo '[代理商]数据插入失败：' . $e->getMessage() . PHP_EOL;
        }
        return true;
    }
}
